#include "elog.h"
#include "elog_file.h"
#include "img_utils.h"
#include "file_utils.h"

#include <fstream>
#include <string>


int saveNV12ToJpg(const uint8_t* nv12_data, int width, int height, const std::string& file_name) {
    // log_i("saveNV12ToJpg");
    cv::Mat yuv_img(height + height / 2, width, CV_8UC1, (void*)nv12_data);
    cv::Mat bgr_img;
    cv::cvtColor(yuv_img, bgr_img, cv::COLOR_YUV2BGR_NV12);

    return cv::imwrite(file_name, bgr_img);
}

void saveNV12ToJpgWithResize(const uint8_t* nv12_data, int width, int height, const std::string& file_name, int target_width, int target_height) {
    cv::Mat yuv_img(height + height / 2, width, CV_8UC1, (void*)nv12_data);
    cv::Mat bgr_img;
    cv::cvtColor(yuv_img, bgr_img, cv::COLOR_YUV2BGR_NV12);
    cv::Mat resized_mat;
    cv::resize(bgr_img, resized_mat, cv::Size(target_width, target_height));

    cv::imwrite(file_name, bgr_img);
}

void imageDownsample(const std::string& input_path, const std::string& output_path, int target_width, int target_height) {
    cv::Mat original_image = cv::imread(input_path, cv::IMREAD_UNCHANGED);
    log_i("imageDownsample input_path = %s", input_path.c_str());
    
    if (original_image.empty()) {
        log_e("nable to read the input image from %s", input_path.c_str());
        return;
    }

    cv::Mat downsampled_image;
    cv::resize(original_image, downsampled_image, cv::Size(target_width, target_height), 0, 0, cv::INTER_AREA);

    cv::imwrite(output_path, downsampled_image);

    fileSync();

    log_i("Image downsampled and saved to %s", output_path.c_str());
}

void nv12ToJpgWithCropAndResize(const uint8_t* nv12_data, int width, int height, const std::string& file_name, int x, int y, int ratio) {
    // Create a Mat object to hold the NV12 data
    cv::Mat yuv_img(height + height / 2, width, CV_8UC1, (void*)nv12_data);

    // Calculate the coordinates for the cropping region
    int crop_x = std::max(0, x - (width / (2 * ratio))); // Left boundary
    int crop_y = std::max(0, y - (height / (2 * ratio))); // Top boundary
    int crop_width = std::min(width - crop_x, (width / ratio)); // Width of the cropped region
    int crop_height = std::min(height - crop_y, (height / ratio)); // Height of the cropped region

    log_i("crop_x = %d, crop_y = %d, crop_width = %d, crop_height = %d", crop_x, crop_y, crop_width, crop_height);

    cv::Mat bgr_img;
    cv::cvtColor(yuv_img, bgr_img, cv::COLOR_YUV2BGR_NV12);
    cv::Rect roi(crop_x, crop_y, crop_width, crop_height);
    cv::Mat cropped_bgr = bgr_img(roi);

    cv::Mat resized_mat;
    cv::resize(cropped_bgr, resized_mat, cv::Size(crop_width * ratio, crop_height * ratio));

    cv::imwrite(file_name, resized_mat);
}

cv::Size getImageSize(const std::string& input_path) {
    cv::Mat image = cv::imread(input_path);
    
    if (image.empty()) {
        return cv::Size(0, 0);
    }

    cv::Size size = image.size();

    return size;
}

